/*
This is part of Screenbar, which is based in part on the Litestep
shell source code.

Copyright (C) 2008-2009 Jim Babcock
Copyright (C) 1997-2009 The LiteStep Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "stdafx.h"

void warn(const char *warning)
{
	trace << "WARNING: "<<warning<<"\n";;
	MessageBoxA(NULL, warning, PROJECT_NAME, MB_TOPMOST);
}

set<string> warningsGiven;
void warnOnce(const char *warning)
{
	if(warningsGiven.find(string(warning)) != warningsGiven.end())
		return;
	warningsGiven.insert(warning);
	warn(warning);
}

void fatal(const char *error)
{
	trace << "Fatal error: "<<error<<"\n";
	MessageBoxA(NULL, error, PROJECT_NAME, MB_TOPMOST);
	throw;
}

HWND getDesktopWindow()
{
	HWND desktop = FindWindowA("DesktopBackgroundClass", NULL);
	if (!desktop)
		desktop = GetDesktopWindow();
	return desktop;
}

Point getCursorPos()
{
	CURSORINFO cursorInfo;
	cursorInfo.cbSize = sizeof(CURSORINFO);
	
	GetCursorInfo(&cursorInfo);
	return cursorInfo.ptScreenPos;
}

string retprintf(const char *fmt, ...)
{
	char buf[4096];
	va_list args;
	va_start(args, fmt);
	vsnprintf(buf, 4096, fmt, args);
	va_end(args);
	return buf;
}

void tokenizeString(const string &str, vector<string> &result, const char *separators)
{
	char *copy = _strdup(str.c_str());
	char *pos = strtok(copy, separators);
	while(pos) {
		result.push_back(pos);
		pos = strtok(NULL, separators);
	}
	free(copy);
}

const char *skipwhitespace(const char *pos)
{
	while(*pos && isspace(*pos))
		pos++;
	return pos;
}

vector<string> separateArgs(const char *args)
{
	const char *pos = args;
	char buf[4096];
	vector<string> ret;
	
	while(GetToken(pos, buf, &pos, 0))
		ret.push_back(string(buf));
	
	return ret;
}

string to_lower(string str)
{
	string ret(str);
	for(size_t ii=0; ii<ret.size(); ii++)
		ret[ii] = tolower(ret[ii]);
	return ret;
}

string getWindowsErr()
{
	DWORD err = GetLastError();
	LPSTR output;
	
	FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
		0, err, 0,
		(LPSTR)&output, 32, NULL);
	
	string ret = string(output);
	LocalFree(output);
	
	return ret;
}

UINT64 getSystemTime()
{
	FILETIME currentTime;
	GetSystemTimeAsFileTime(&currentTime);
	return Time64fromFileTime(currentTime);
}

UINT64 Time64fromFileTime(FILETIME fileTime)
{
	return ((UINT64)fileTime.dwHighDateTime<<32) + (UINT64)fileTime.dwLowDateTime;
}

Direction parseDirection(string direction)
{
	direction = to_lower(direction);
	if(direction == "up")
		return directionUp;
	else if(direction == "right")
		return directionRight;
	else if(direction == "down")
		return directionDown;
	else if(direction == "left")
		return directionLeft;
	else
		return directionUnspecified;
}

/////////////////////////////////////////////////////////////////////////////

BackBuffer::BackBuffer(int width, int height)
{
	BITMAPV4HEADER bmpHeader;
	memset(&bmpHeader, 0, sizeof(bmpHeader));
	bmpHeader.bV4Size = sizeof(bmpHeader);
	bmpHeader.bV4Width = width;
	bmpHeader.bV4Height = height;
	bmpHeader.bV4Planes = 1;
	bmpHeader.bV4BitCount = 32;
	bmpHeader.bV4V4Compression = BI_RGB;
	bmpHeader.bV4SizeImage = width*height*4;
	bmpHeader.bV4RedMask   = 0x000000FF;
	bmpHeader.bV4GreenMask = 0x0000FF00;
	bmpHeader.bV4BlueMask  = 0x00FF0000;
	bmpHeader.bV4AlphaMask = 0xFF000000;
	bmpHeader.bV4CSType = LCS_WINDOWS_COLOR_SPACE;
	
	HDC screenDC = GetDC(0);
	hdc = CreateCompatibleDC(screenDC);
	ReleaseDC(0, screenDC);
	
	bmp = CreateDIBSection(hdc, (BITMAPINFO*)&bmpHeader, DIB_RGB_COLORS, &bits, NULL, 0);
	
	oldBmp = (HBITMAP)SelectObject(hdc, bmp);
}

BackBuffer::~BackBuffer()
{
	SelectObject(hdc, oldBmp);
	DeleteObject(bmp);
	DeleteDC(hdc);
}

void *BackBuffer::getBits()
{
	return bits;
}

HDC BackBuffer::getDC()
{
	return hdc;
}
